﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Reflection;

using Microsoft.Xna.Framework.Graphics;
using TomShane.Neoforce.Controls;

using UnitShared;
using tactics.Interfaces;

namespace tactics.GUI
{
    using TextProperties = Utility.Pair<TextBox, string>;
    using AbilityList = List<Abilities.Ability>;

    public class UnitCard : IGUIParsable
    {
        public enum LayoutOptions
        {
            Right,
            Left,
        }      
        
        Manager guiManager;
        AbilityCardManager abilityDisplay;
        StatusDisplayManager statusDisplay;
        string statusXmlFile;

        Panel backPanel;
        ImageBox cardTop;
        ImageBox cardBottom;
        ImageBox movementType;
        Dictionary<string, TextProperties> text;

        Unit unit; // currently focused unit
        bool focused;
        bool enabled;

        Color nameColour;

        LayoutOptions statusLayout;
        
        #region Properties

        public bool HasFocus
        {
            get { return focused; }
            set { focused = value; }
        }

        public bool Visible
        {
            get { return backPanel.Visible; }
            set { backPanel.Visible = value; if (value == false) ClearUnitFocus(); }
        }

        public bool Enabled
        {
            get { return enabled; }
            set { enabled = value; UpdateEnabled(); }
        }

        public Unit UnitFocus
        {
            get { return unit; }
            set 
            {   
                unit = value;
                if (unit != null)
                {
                    SetInfoDisplay();
                }
            }
        }

        public Color NameColour
        {
            get { return nameColour; }
            set { nameColour = value; }
        }

        public int Width
        {
            get { return backPanel.Width; }
        }

        #endregion

        public UnitCard(Manager guiManagerIn, List<Abilities.Ability> abilityList, string xmlFile, string statusXmlFileIn, string abilityXmlFileIn, LayoutOptions statusLayoutIn)
        {
            statusXmlFile = statusXmlFileIn;
            statusLayout = statusLayoutIn;

            InitControls(guiManagerIn);
            GUIBuilder.BuildGUI(this, guiManagerIn, xmlFile, "UnitCard");

            abilityDisplay = new GUI.AbilityCardManager(guiManagerIn, abilityXmlFileIn, abilityList, backPanel.Left, backPanel.Top + backPanel.Height + 2);
        }

        public void Remove()
        {
            if (statusDisplay != null)
                statusDisplay.Remove();
            guiManager.Remove(backPanel);
        }

        #region Initialize Controls

        private void InitControls(Manager guiManagerIn)
        {
            text = new Dictionary<string, TextProperties>();

            focused = false;
            enabled = true;

            guiManager = guiManagerIn;

            backPanel = new Panel(guiManager);
            backPanel.Init();
            backPanel.Visible = false;

            cardBottom = new ImageBox(guiManager);
            cardBottom.Init();
            cardBottom.SizeMode = SizeMode.Stretched;

            cardTop = new ImageBox(guiManager);
            cardTop.Init();
            cardTop.SizeMode = SizeMode.Stretched;

            movementType= new ImageBox(guiManager);
            movementType.Init();
            movementType.SizeMode = SizeMode.Stretched;
        }

        #endregion

        #region Display Unit Properties

        private void SetInfoDisplay()
        {
            text["PointText"].First.Text = string.Format(text["PointText"].Second, unit.PointCost);
            text["PointText"].First.Skin.Layers[0].Text.Font.Resource = TacticsEngine.Instance.Content.Load<SpriteFont>(@"fonts\Arial-Large");

            text["HealthText"].First.Text = string.Format(text["HealthText"].Second, unit.CurrentHp, unit.Hp);
            text["HealthText"].First.Skin.Layers[0].Text.Font.Resource = TacticsEngine.Instance.Content.Load<SpriteFont>(@"fonts\Arial-Large");
            
            text["AttackText"].First.Text = string.Format(text["AttackText"].Second, unit.CurrentAttack);
            text["AttackText"].First.Skin.Layers[0].Text.Font.Resource = TacticsEngine.Instance.Content.Load<SpriteFont>(@"fonts\Arial-Medium");

            text["DefenseText"].First.Text = string.Format(text["DefenseText"].Second, unit.CurrentDefense);
            text["DefenseText"].First.Skin.Layers[0].Text.Font.Resource = TacticsEngine.Instance.Content.Load<SpriteFont>(@"fonts\Arial-Medium");

            text["MagicText"].First.Text = string.Format(text["MagicText"].Second, unit.CurrentMagic);
            text["MagicText"].First.Skin.Layers[0].Text.Font.Resource = TacticsEngine.Instance.Content.Load<SpriteFont>(@"fonts\Arial-Medium");

            text["MagicDefenseText"].First.Text = string.Format(text["MagicDefenseText"].Second, unit.CurrentMagicDefense);
            text["MagicDefenseText"].First.Skin.Layers[0].Text.Font.Resource = TacticsEngine.Instance.Content.Load<SpriteFont>(@"fonts\Arial-Medium");

            text["DescriptionText"].First.Text = string.Format(text["DescriptionText"].Second, unit.Description);
            text["DescriptionText"].First.Skin.Layers[0].Text.Font.Resource = TacticsEngine.Instance.Content.Load<SpriteFont>(@"fonts\Arial-Small");

            text["SpeedText"].First.Text = string.Format(text["SpeedText"].Second, unit.CurrentSpeed);
            text["SpeedText"].First.Skin.Layers[0].Text.Font.Resource = TacticsEngine.Instance.Content.Load<SpriteFont>(@"fonts\Arial-Huge");

            cardBottom.Image = TacticsEngine.Instance.Content.Load<Texture2D>("gui/unitcard/card_" + unit.Faction + "_bottom");
            cardTop.Image = TacticsEngine.Instance.Content.Load<Texture2D>("gui/unitcard/card_" + unit.Faction + "_top_" + unit.Name.Substring(0, 4));

            movementType.Image = TacticsEngine.Instance.Content.Load<Texture2D>("gui/movementtypes/" + 
                                 TacticsEngine.Instance.Game.TurnManager.MovementRuleSet.GetMovementTypeByName(unit.MovementType).Texture);

            abilityDisplay.ShowCardsForUnit(unit);

            if (statusDisplay == null)
            {
                int x = backPanel.Left;
                int y = backPanel.Top;

                if (statusLayout == LayoutOptions.Right)
                    x += backPanel.Width + 2;
                else
                    x -= 34;

                statusDisplay = new StatusDisplayManager(guiManager, statusXmlFile, unit, StatusDisplayManager.LayoutOptions.Down1C, x, y);
                statusDisplay.ShowCards();
            }
        }

        public void UpdatePosition(int x, int y)
        {
            backPanel.Left = x;
            backPanel.Top = y;
            
            abilityDisplay.UpdatePosition(backPanel.Left, backPanel.Top + backPanel.Height + 2);
        }

        private void ClearUnitFocus()
        {
            unit = null;
            focused = false;

            if (statusDisplay != null)
            {
                statusDisplay.HideCards();
                statusDisplay = null;
            }

            abilityDisplay.HideCards();
        }

        private void UpdateEnabled()
        {
            if (!enabled)
            {
                backPanel.Visible = false;
            }
        }

        #endregion

        #region Parsing Interface

        public Control Parse(XmlReader r, string controlName)
        {
            Control found = null;

            if (controlName == "BackPanel")
            {
                GUIBuilder.ParseControl<Panel>(r, backPanel);
                found = backPanel;
            }
            else if (controlName == "CardTop")
            {
                GUIBuilder.ParseControl<ImageBox>(r, cardTop);
                found = cardTop;
            }
            else if (controlName == "CardBottom")
            {
                GUIBuilder.ParseControl<ImageBox>(r, cardBottom);
                found = cardBottom;
            }
            else if (controlName == "MovementType")
            {
                GUIBuilder.ParseControl<ImageBox>(r, movementType);
                found = movementType;
            }
            else if (controlName.EndsWith("Text"))
            {
                text.Add(controlName, new TextProperties());

                TextBox tmp = new TextBox(guiManager);
                tmp.Init();
                GUIBuilder.ParseControl<TextBox>(r, tmp);
                text[controlName].Second = tmp.Text;
                found = tmp;

                text[controlName].First = tmp;
            }

            return found;
        }

        #endregion

    }
}
